/*
 * Copyright 2014-2016 wjokhttp
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mainaer.wjoklib.okhttp.upload;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;

/**
 * 上传管理器
 *
 * @author wangjian
 * @date 2016/5/13 .
 */
public class UploadManager {

    static UploadManager manager;
    private OkHttpClient mClient;
    private int mPoolSize = 20;
    // 将执行结果保存在future变量中
    private Map<String, Future> mFutureMap;
    private ExecutorService mExecutor;
    private Map<String, UploadTask> mCurrentTaskList;

    public UploadManager() {
        initOkhttpClient();

        // 初始化线程池
        mExecutor = Executors.newFixedThreadPool(mPoolSize);
        mFutureMap = new ConcurrentHashMap<>();
        mCurrentTaskList = new ConcurrentHashMap<>();
    }

    /**
     * 获得当前对象实例
     *
     * @return 当前实例对象
     */
    public final static UploadManager getInstance() {
        if (manager == null) {
            synchronized (UploadManager.class) {
                if (manager == null) {
                    manager = new UploadManager();
                }
            }
        }
        return manager;
    }

    /**
     * 初始化okhttp
     */
    private void initOkhttpClient() {
        OkHttpClient.Builder okBuilder = new OkHttpClient.Builder();
        okBuilder.connectTimeout(1000, TimeUnit.SECONDS);
        okBuilder.readTimeout(1000, TimeUnit.SECONDS);
        okBuilder.writeTimeout(1000, TimeUnit.SECONDS);
        mClient = okBuilder.build();
    }

    /**
     * 添加上传任务
     *
     * @param uploadTask
     */
    public void addUploadTask(UploadTask uploadTask) {
        if (uploadTask != null && !isUploading(uploadTask)) {
            uploadTask.setMClient(mClient);
            uploadTask.setUploadStatus(UploadStatus.UPLOAD_STATUS_INIT);
            // 保存上传task列表
            mCurrentTaskList.put(uploadTask.getId(), uploadTask);
            Future future = mExecutor.submit(uploadTask);
            mFutureMap.put(uploadTask.getId(), future);
        }
    }

    private boolean isUploading(UploadTask task) {
        if (task == null) {
            return false;
        }
        return task.getUploadStatus() == UploadStatus.UPLOAD_STATUS_UPLOADING;
    }

    /**
     * 暂停上传任务
     *
     * @param id 任务id
     */
    public void pause(String id) {
        UploadTask task = getUploadTask(id);
        if (task != null) {
            task.setUploadStatus(UploadStatus.UPLOAD_STATUS_PAUSE);
        }
    }

    /**
     * 重新开始已经暂停的上传任务
     *
     * @param id 任务id
     */
    public void resume(String id, UploadTaskListener listener) {
        UploadTask task = getUploadTask(id);
        if (task != null) {
            addUploadTask(task);
        }
    }

    /**
     * 实时更新manager中的task信息
     *
     * @param task
     */
    public void updateUploadTask(UploadTask task) {
        if (task != null) {
            UploadTask currTask = getUploadTask(task.getId());
            if (currTask != null) {
                mCurrentTaskList.put(task.getId(), task);
            }
        }
    }

    /**
     * 获得指定的task
     *
     * @param id task id
     * @return
     */
    public UploadTask getUploadTask(String id) {
        UploadTask currTask = mCurrentTaskList.get(id);
        if (currTask == null) {
            currTask = new UploadTask()
                    .setUploadStatus(UploadStatus.UPLOAD_STATUS_INIT);
            // 放入task list中
            mCurrentTaskList.put(id, currTask);
        }
        return currTask;
    }

}
